package svc

import (
	"fmt"
	"gitee.com/gopher2011/go-crud/internal/config"
	"gitee.com/gopher2011/go-crud/internal/types"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	_ "github.com/jinzhu/gorm/dialects/postgres"
	"github.com/kotlin2018/mbt"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/syncx"
	"gorm.io/driver/sqlserver"
	v2 "gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"strconv"
)

var Svc *ServiceContext

type ServiceContext struct {
	Config config.Config
	DB     *gorm.DB
	DB2    *v2.DB
	Cache  cache.Cache
}

func NewServiceContext(c config.Config) {
	var (
		dsn string
		err error
	)
	Svc = &ServiceContext{
		Config: c,
		Cache:  cache.New(c.CacheRedis, syncx.NewSingleFlight(), cache.NewStat(""), nil),
	}
	C := &mbt.Database{
		Pkg:        c.Database.Pkg,
		DriverName: c.Database.DriverName,
		Logger: &mbt.Logger{
			PrintSql: true,
			PrintXml: false,
			Path:     c.Database.LogPath,
		},
	}
	switch c.Database.DriverName {
	case "mysql":
		dsn = c.Database.User + ":" + c.Database.Password + "@tcp(" + c.Database.Host + ":" + strconv.Itoa(c.Database.Port) + ")/" + c.Database.DBName + "?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
		Svc.DB, err = gorm.Open("mysql", dsn)
		C.DSN = dsn
	case "postgres":
		dsn = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable TimeZone=Asia/Shanghai", c.Database.Host, c.Database.Port, c.Database.User, c.Database.Password, c.Database.DBName)
		Svc.DB, err = gorm.Open("postgres", dsn)
		C.DSN = dsn
	case "mssql":
		dsn = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", c.Database.User, c.Database.Password, c.Database.Host, c.Database.Port, c.Database.DBName)
		Svc.DB2, err = v2.Open(sqlserver.Open(dsn), &v2.Config{
			SkipDefaultTransaction: false, //启用事务
			NamingStrategy: schema.NamingStrategy{
				TablePrefix:   "",   //表前缀
				SingularTable: true, //使用单数表名
			},
			DryRun:                                   false,                               //禁止SQL空跑
			DisableForeignKeyConstraintWhenMigrating: true,                                //创建逻辑外键
			Logger:                                   logger.Default.LogMode(logger.Info), //输出 SQL语句
		})
		C.DSN = dsn
	}
	if err != nil {
		log.Fatalln("connect database err", err)
	}
	mbt.New(C).Run()
}

func (it *ServiceContext) AutoMigrate() {
	it.DB.SingularTable(true)
	it.DB.AutoMigrate(
		&types.Response{},
	)
}
